# -*- coding: utf-8 -*-
import ast
import hashlib
import json
from collections import OrderedDict

import requests
from django.conf import settings

from async import async_job
from common.agentpay.base import AbstractHandler
from common.agentpay.db import get_agent_pay_order
from common.agentpay.model import AGENT_PAY_STATUS
from common.cache import redis_cache
from common.channel import admin_db as channel_admin_db
from common.channel.pay import check_channel_order
from common.order import db as order_db
from common.order.model import PAY_STATUS
from common.utils import track_logging
from common.utils.exceptions import ParamError
from common.utils.ip_address import check_valid_ip_address
from common.utils.types import Enum

_LOGGER = track_logging.getLogger(__name__)

APP_CONF = {
    '666002': {
        # tt支付 微信扫码 3.5% 50-5000 dwc
        'API_KEY': 'q64eLiGVdwEDo-p8pBKD326sGseZ_jf0',
        'gateway': 'http://dwc.ttpay365.com/api/charge/redirect',
        'query_gateway': 'http://dwc.ttpay365.com/api/out/query-charge-front',
        'draw_gateway': 'http://dwc.ttpay365.com/api/withdraw/do',
        'draw_query_gateway': 'http://dwc.ttpay365.com/api/withdraw/query',
        'balance_query_gateway': 'http://dwc.ttpay365.com/api/withdraw/bal',
    },
    '666004': {
        # tt支付 支付宝扫码 3.5% 10-3000 zs
        'API_KEY': 'm0GP3ziJZt-xzh5jn4gMOoRw8HmMXC5D',
        'gateway': 'http://dwc.ttpay365.com/api/charge/redirect',
        'query_gateway': 'http://dwc.ttpay365.com/api/out/query-charge-front',
        'draw_gateway': 'http://dwc.ttpay365.com/api/withdraw/do',
        'draw_query_gateway': 'http://dwc.ttpay365.com/api/withdraw/query',
    },
    '666005': {
        # tt支付 支付宝扫码 3.5% 10-3000 witch
        'API_KEY': 'VmZ5PMOB9X0VW-cdiyknYVB9LyVAX_32',
        'gateway': 'http://dwc.ttpay365.com/api/charge/redirect',
        'query_gateway': 'http://dwc.ttpay365.com/api/out/query-charge-front',
        'draw_gateway': 'http://dwc.ttpay365.com/api/withdraw/do',
        'draw_query_gateway': 'http://dwc.ttpay365.com/api/withdraw/query',
    },
    '666006': {
        # tt支付 支付宝扫码 3.5% 10-3000 loki
        'API_KEY': 'vCfkxyQU4d0bah3k0dF8_vPiJOMOmL4p',
        'gateway': 'http://dwc.ttpay365.com/api/charge/redirect',
        'query_gateway': 'http://dwc.ttpay365.com/api/out/query-charge-front',
        'draw_gateway': 'http://dwc.ttpay365.com/api/withdraw/do',
        'draw_query_gateway': 'http://dwc.ttpay365.com/api/withdraw/query',
    },
    '666008': {
        # tt支付 支付宝扫码/微信扫码 3.5% 10-3000 tt
        'API_KEY': 'KbYU6lkQPRbQGJXLAELq_h8AW_mXsHMK',
        'gateway': 'http://dwc.ttpay365.com/api/charge/redirect',
        'query_gateway': 'http://dwc.ttpay365.com/api/out/query-charge-front',
        'draw_gateway': 'http://dwc.ttpay365.com/api/withdraw/do',
        'draw_query_gateway': 'http://dwc.ttpay365.com/api/withdraw/query',
    },
    '666021': {
        # tt支付 微信扫码 3.5% 200-20000 dwc
        'API_KEY': '2HecaFPFSaiLpr6YPgBuaJWqep7ZSOSS',
        'gateway': 'http://dwc.ttpay365.com/api/charge/redirect',
        'query_gateway': 'http://dwc.ttpay365.com/api/out/query-charge-front',
        'draw_gateway': 'http://dwc.ttpay365.com/api/withdraw/do',
        'draw_query_gateway': 'http://dwc.ttpay365.com/api/withdraw/query',
    },

    '666059': {
        # tt支付 云闪付 1.6% 50-5000 dwc
        'API_KEY': 'g6wUKgrFGZNp1f0-f-qmduGJctkyzrNo',
        'gateway': 'http://dwc.ttpay365.com/api/charge/redirect',
        'query_gateway': 'http://dwc.ttpay365.com/api/out/query-charge-front',
        'draw_gateway': 'http://dwc.ttpay365.com/api/withdraw/do',
        'draw_query_gateway': 'http://dwc.ttpay365.com/api/withdraw/query',
    },
    '666060': {
        # tt支付 云闪付 1.6% 50-5000 witch
        'API_KEY': 'NDls9CmPuh_l7DZsltMQ7PcQoYGxrU3b',
        'gateway': 'http://dwc.ttpay365.com/api/charge/redirect',
        'query_gateway': 'http://dwc.ttpay365.com/api/out/query-charge-front',
        'draw_gateway': 'http://dwc.ttpay365.com/api/withdraw/do',
        'draw_query_gateway': 'http://dwc.ttpay365.com/api/withdraw/query',
    },
    '666061': {
        # tt支付 云闪付 1.6% 50-5000 loki
        'API_KEY': 'WFtOzJzbbL9Y7UrImNHl45K4ne1yAEV1',
        'gateway': 'http://dwc.ttpay365.com/api/charge/redirect',
        'query_gateway': 'http://dwc.ttpay365.com/api/out/query-charge-front',
        'draw_gateway': 'http://dwc.ttpay365.com/api/withdraw/do',
        'draw_query_gateway': 'http://dwc.ttpay365.com/api/withdraw/query',
    },
    '666062': {
        # tt支付 云闪付 1.6% 50-5000 zs
        'API_KEY': 'EzOuYBgYnFCom2-N3tcleAjmTpMPAn_u',
        'gateway': 'http://dwc.ttpay365.com/api/charge/redirect',
        'query_gateway': 'http://dwc.ttpay365.com/api/out/query-charge-front',
        'draw_gateway': 'http://dwc.ttpay365.com/api/withdraw/do',
        'draw_query_gateway': 'http://dwc.ttpay365.com/api/withdraw/query',
    },
    '666063': {
        # tt支付 云闪付 1.6% 50-5000 tt
        'API_KEY': '1TIraGLoJoRhjsqraoLru8JTY1hFgphB',
        'gateway': 'http://dwc.ttpay365.com/api/charge/redirect',
        'query_gateway': 'http://dwc.ttpay365.com/api/out/query-charge-front',
        'draw_gateway': 'http://dwc.ttpay365.com/api/withdraw/do',
        'draw_query_gateway': 'http://dwc.ttpay365.com/api/withdraw/query',
    },
}


def _get_api_key(mch_id):
    return APP_CONF[mch_id]['API_KEY']


def _get_gateway(mch_id):
    return APP_CONF[mch_id]['gateway']


def _get_query_gateway(mch_id):
    return APP_CONF[mch_id]['query_gateway']


def _get_draw_gateway(mch_id):
    return APP_CONF[mch_id]['draw_gateway']


def _get_draw_query_gateway(mch_id):
    return APP_CONF[mch_id]['draw_query_gateway']


def _get_balance_gateway(mch_id):
    return APP_CONF[mch_id]['balance_query_gateway']


def _gen_sign(s):
    m = hashlib.md5()
    m.update(s.encode('utf8'))
    sign = m.hexdigest().lower()
    return sign


def generate_sign(parameter, key):
    s = ''
    for k in sorted(parameter.keys()):
        s += '%s=%s&' % (k, parameter[k])
    s += 'secret=%s' % key
    return _gen_sign(s)


def verify_notify_sign(params, key):
    sign = params['sign']
    params.pop('sign')
    calculated_sign = generate_sign(params, key)
    if sign.lower() != calculated_sign.lower():
        _LOGGER.info("ttpay sign: %s, calculated sign: %s", sign, calculated_sign)
        raise ParamError('sign not pass, data: %s' % params)


def _get_pay_type(service):
    if service == 'wechatscan':
        return 666008
    elif service == 'alipayscan':
        return 666003
    elif service == 'cloudpay':
        return 666006
    elif service == 'cloud_flash':
        return 666015
    return 666002


def _build_form(params, gateway):
    html = u"<head><title>loading...</title></head><form id='submit' name='submit' action='" + gateway + "' method='post'>"
    for k, v in params.items():
        html += "<input type='hidden' name='%s' value='%s'/>" % (k, v)
    html += "</form>"
    html += "<script>doc" \
            "ument.forms['submit'].submit();</script>"
    return html


def create_charge(pay, pay_amount, info):
    service = info.get('service')
    app_id = info['app_id']
    api_key = _get_api_key(app_id)
    parameter_dict = OrderedDict((
        ('order_id', int(pay.id)),
        ('mer_id', int(app_id)),
        ('amount', int(pay_amount * 100)),
        ('uid', pay.user_id),
        ('product_id', _get_pay_type(service)),
        ('front_url', '{}/pay/api/{}/ttpay/{}/'.format(settings.NOTIFY_PREFIX, settings.RETURN_PATH, pay.id)),
        ('back_url', '{}/pay/api/{}/ttpay/{}'.format(settings.NOTIFY_PREFIX, settings.NOTIFY_PATH, app_id)),
    ))
    parameter_dict['sign'] = generate_sign(parameter_dict, api_key)
    _LOGGER.info("ttpay create: %s, order_id is: %s", json.dumps(parameter_dict), parameter_dict['order_id'])
    html_text = _build_form(parameter_dict, _get_gateway(app_id))
    cache_id = redis_cache.save_html(pay.id, html_text)
    _LOGGER.info('ttpay url: %s', settings.PAY_CACHE_URL + cache_id)
    return {'charge_info': settings.PAY_CACHE_URL + cache_id}


# OK
def check_notify_sign(request, app_id):
    api_key = _get_api_key(app_id)
    data = dict(request.POST.iteritems())
    _LOGGER.info("ttpay notify data: %s, order_id is: %s", data, data['order_id'])
    verify_notify_sign(data, api_key)
    pay_id = data['order_id']
    check_valid_ip_address(str(request.META['REMOTE_ADDR']), pay_id)
    if not pay_id:
        _LOGGER.error("fatal error, out_trade_no not exists, data: %s", data)
        raise ParamError('ttpay event does not contain pay ID')

    pay = order_db.get_pay(int(pay_id))
    if not pay:
        raise ParamError('pay_id: %s invalid' % pay_id)
    if pay.status != PAY_STATUS.READY:
        raise ParamError('pay %s has been processed' % pay_id)

    mch_id = pay.mch_id  # 商户编号
    trade_status = int(data['status'])
    trade_no = pay.third_id
    total_fee = float(data['amount']) / 100.0
    extend = {
        'trade_status': trade_status,
        'trade_no': trade_no,
        'total_fee': total_fee,
    }

    check_channel_order(pay_id, total_fee, app_id)
    if trade_status == 2:
        _LOGGER.info('ttpay check order success, mch_id:%s pay_id:%s' % (mch_id, pay_id))
        order_db.add_pay_success(mch_id, pay_id, total_fee, trade_no, extend)
        # async notify
        async_job.notify_mch(pay_id)


def query_charge(pay_order, app_id):
    """ 查询订单 """
    pay_id = pay_order.id
    api_key = _get_api_key(app_id)
    dct = OrderedDict((
        ('order_id', int(pay_id)),
        ('mer_id', int(app_id)),
    ))
    dct['sign'] = generate_sign(dct, api_key)
    headers = {'Content-Type': 'application/x-www-form-urlencoded'}
    _LOGGER.info('ttpay query data: %s, order_id is: %s', json.dumps(dct), dct['order_id'])
    response = requests.post(_get_query_gateway(app_id), data=dct, headers=headers, timeout=3)
    _LOGGER.info('ttpay query rsp: %s', response.text)
    data = json.loads(response.text)
    if response.status_code == 200:
        trade_status = int(data['data']['status'])
        total_fee = float(data['data']['amount']) / 100.0
        trade_no = str(data['data']['payOrderId'])
        extend = {
            'trade_status': trade_status,
            'trade_no': trade_no,
            'total_fee': total_fee
        }
        if trade_status == 2:
            _LOGGER.info('ttpay query order success, mch_id:%s pay_id:%s' % (pay_order.mch_id, pay_order.id))
            order_db.add_pay_success(pay_order.mch_id, pay_order.id, total_fee, trade_no, extend)
            async_job.notify_mch(pay_order.id)
    else:
        _LOGGER.warn('ttpay data error, status_code: %s', response.status_code)


def _get_bank_name(bank_type):
    if bank_type == 'ICBC':
        return '工商银行'
    elif bank_type == 'CCB':
        return '建设银行'
    elif bank_type == 'PNB':
        return '平安银行'
    elif bank_type == 'BOC':
        return '中国银行'
    elif bank_type == 'ABC':
        return '农业银行'
    elif bank_type == 'BCM':
        return '交通银行'
    elif bank_type == 'CMB':
        return '招商银行'
    elif bank_type == 'CNCB':
        return '中信银行'
    elif bank_type == 'CEB':
        return '光大银行'
    elif bank_type == 'HXB':
        return '华夏银行'
    elif bank_type == 'SPDB':
        return '浦发银行'
    elif bank_type == 'CIB':
        return '兴业银行'
    elif bank_type == 'CMBC':
        return '民生银行'
    elif bank_type == 'CGB':
        return '广发银行'
    elif bank_type == 'PSBC':
        return '邮政银行'
    else:
        return 'THIRD_NOT_SUPPORT'


NOTIFY_PAY_STATUS = Enum({
    "WAIT": (0, u"等待"),
    "SUCCESS": (1, u"成功"),
    "FAIL": (2, u"失败"),
})


def convert_notify_status(status):
    if status == NOTIFY_PAY_STATUS.SUCCESS:
        return AGENT_PAY_STATUS.SUCCESS
    elif status == NOTIFY_PAY_STATUS.FAIL:
        return AGENT_PAY_STATUS.FAIL
    elif status == NOTIFY_PAY_STATUS.WAIT:
        return AGENT_PAY_STATUS.SUBMIT


class TtPayHandler(AbstractHandler):

    def submit_order(self, order_no):
        """
        创建代付请求
        :return:
        """
        agent_pay = get_agent_pay_order(order_no)
        chn = channel_admin_db.get_channel(int(agent_pay.channel_id))

        chn_info = json.loads(chn.info)
        app_id = chn_info['app_id']
        params = {
            'mer_id': app_id,
            'bank_name': _get_bank_name(agent_pay.bank_code).encode('utf-8'),
            'account_name': agent_pay.account_name,
            'account_no': agent_pay.card_no,
            'order_id': agent_pay.order_no,
            'amount': int(agent_pay.total_fee * 100),
            'bank_open': agent_pay.bank_name.encode('utf-8'),
            'province': agent_pay.account_province.encode('utf-8'),
            'channel_id': '0',
            'type': 1,
        }
        params['sign'] = generate_sign(params, _get_api_key(app_id))
        _LOGGER.info('ttpay draw data: %s', json.dumps(params))
        headers = {'Content-Type': 'application/x-www-form-urlencoded'}
        response = requests.post(_get_draw_gateway(app_id), data=params, timeout=3, headers=headers, verify=False)
        _LOGGER.info("ttpay draw rsp data: %s %s", response.status_code, response.text)
        data = json.loads(response.text)['data']
        # 􏰍􏰓􏱽􏱾􏲟􏲏􏰤 0 订单生成 1 支付中 2 支付成功 3 支付失败 4 未发送成功
        if data['status'] == 2:
            return params['order_id'], '', '代付成功->' + str(response.text)
        else:
            return params['order_id'], '', '其他状态->' + str(response.text)

    def agent_pay_notify(self, order_no, status, pay_fee):
        pass

    def query_agent_pay(self, order_no):
        """
        查询代付请求
        :return:
        """
        agent_pay = get_agent_pay_order(order_no)
        chn = channel_admin_db.get_channel(int(agent_pay.channel_id))
        chn_info = json.loads(chn.info)
        app_id = chn_info['app_id']
        params = {
            'order_id': agent_pay.order_no,
            'mer_id': app_id,
        }
        params['sign'] = generate_sign(params, _get_api_key(app_id))
        _LOGGER.info('ttpay draw query data: %s', json.dumps(params))
        headers = {'Content-Type': 'application/x-www-form-urlencoded'}
        response = requests.post(_get_draw_query_gateway(app_id), data=params, timeout=3, headers=headers, verify=False)
        _LOGGER.info("ttpay draw query rsp data: %s %s", response.status_code, response.text)

        if response.status_code != 200:
            raise ParamError('ttpay query_agent_pay error')
        data = json.loads(response.text)['data']
        # 􏰍􏰓􏱽􏱾􏲟􏲏􏰤 0 订单生成 1 支付中 2 支付成功 3 支付失败 4 未发送成功
        if data['status'] == 0:
            results = '订单生成->' + str(response.text)
        elif data['status'] == 1:
            results = '支付中->' + str(response.text)
        elif data['status'] == 2:
            results = '支付成功->' + str(response.text)
        elif data['status'] == 3:
            results = '支付失败->' + str(response.text)
        elif data['status'] == 4:
            results = '未发生成功->' + str(response.text)
        else:
            results = '未知状态->' + str(response.text)
        return results

    def query_balance(self, info):
        info = ast.literal_eval(info.encode("utf-8"))
        app_id = info['app_id']
        api_key = _get_api_key(app_id)
        params = {
            'mer_id': app_id,
            'channel_id': '0',
        }
        params['sign'] = generate_sign(params, api_key)
        _LOGGER.info('ttpay balance query data: %s', json.dumps(params))
        headers = {'Content-Type': 'application/x-www-form-urlencoded'}
        response = requests.post(_get_balance_gateway(app_id), data=params, timeout=3, headers=headers, verify=False)
        _LOGGER.info("ttpay balance query rsp data: %s %s", response.status_code, response.text)
        if response.status_code != 200:
            raise ParamError('ttpay query_agent_pay error')
        data = json.loads(response.text)['data']
        return str(
            '总余额' + str(float(data['balance']) / 100.0) + u'元, ' + '可用金额' + str(
                float(data['available']) / 100.0) + u'元, ' + '在途冻结金额' + str(
                float(data['frozen']) / 100.0) + u'元')


handler = TtPayHandler()
